﻿/*1942 game clone
 * Authors:
 * Abdollah Tabareh
 * Bharat Bhushan Konka
 * Martin Svensson 
 * Richard Zianne
 * Tigran Harutyunyan
 * 
 * 2010
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Game1942.Handelers;


namespace Game1942
{
    class GameScene : Scene
    {
        private SpriteBatch _spriteBatch;
        private Texture2D _sprites;
        private SpriteFont _fonts;
        private Game _game;
        private TimeSpan _tmpLastPowerUpAdd;//will be moved to a separate game logic comp.
        private int _mapPosition = -32;
        private Island island;
        private bool _canfire = true;
        private TimeSpan _lastPlayerBullet;
        //Test to add new ennemy
        //private Enemy3 _enemy1, _enemy2;
        //private Bullet bulletTest;
        private Bullet[] _bullets;
        private PowerUp _powerUp;
        private Enemy1[] _wave1Arr;
        private Enemy2[] _wave2Arr;
        private Enemy3[] _wave3Arr;
        private int _bulletConter=0;
        private Handelers.Wave1Handeler wave1;
        private Handelers.Wave2Handeler wave2;
        private Handelers.Wave3Handeler wave3;
        private PlayerPlane _player;
        private BossPlane _boss;
        private int _score;
        private int _numOfPlayerLifes = 3;
        private bool _isTheScoreRecorded = false;
        // Audio effects
        private SoundEffect explosion1;
        private SoundEffect bulletfire;

        private readonly List<GameComponent> _components;
        public List<GameComponent> Components
        {
            get { return _components; }
        }
        public GameScene(Game game, Texture2D sprites, SpriteFont f,SoundEffect explosion,SoundEffect bulletFire) : base(game)
        {
            explosion1 = explosion;
            bulletfire = bulletFire;
            _spriteBatch = (SpriteBatch)game.Services.GetService(typeof(SpriteBatch));
            _sprites = sprites;
            _fonts = f;
            _game = game;
            _components = new List<GameComponent>();
        }
        /// <summary>
        /// Game logic will be implemented here so far but
        /// should be moved to another individual GameLogicManagerComponent later.
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {

            
            KeyboardState keyborard = Keyboard.GetState();
            if (_player._power <= 0 || ((_boss._active) &&(_boss._isDead) && (_numOfPlayerLifes > 0)))
            {
                if (!_isTheScoreRecorded)
                {
                    ScoreManager.saveScore(_score);
                    _isTheScoreRecorded = true;
                }
                if (keyborard.IsKeyDown(Keys.Enter))
                {                    
                    ((Game1) _game).SetCurrentScene(GameScenes.StartScene);
                }
                return;
            }
            if (keyborard.IsKeyDown(Keys.Space))
            {
                if (gameTime.TotalGameTime.Subtract(_lastPlayerBullet).CompareTo(
                new TimeSpan(0, 0, 1)) > 0)
                {
                   _canfire = true;
                   _lastPlayerBullet = gameTime.TotalGameTime;

                   //bullet sound
                   bulletfire.Play();
                }
                
                if (_canfire)
                {
                    //fireBullit(Direction.Up, _player.getPosition(),true);
                    //fireBullit(Direction.UpLeft, _player.getPosition(),true);

                    fireBullit(Direction.Up, new Vector2(_player.getPositionX() + 23, _player.getPositionY()), true);

                    //fireBullit(Direction.Up, new Vector2(_player.getPositionX() + 32,_player.getPositionY()),true);
                    //fireBullit(Direction.UpRight, new Vector2(_player.getPositionX() + 32, _player.getPositionY()),true);
                    _canfire = false;
                }
                
            }
            
            _wave1Arr = wave1.getEnemys();
            _wave2Arr = wave2.getEnemys();
            _wave3Arr = wave3.getEnemys();
            if ((_wave1Arr.Length == 0) && (_wave2Arr.Length == 0))
            {
                if(!_boss._active)
                _boss.activateBoss();
            }
            if (_boss._active)
            {
                bossFire();
            }
            chkCol();

            
            
            if (gameTime.TotalGameTime.Subtract(_tmpLastPowerUpAdd).CompareTo(
                new TimeSpan(0, 0, Util.Instance.RandomGenerator.Next(10,21))) > 0)//if xx sec past from last add of power up
            {
                //Components.Add(new PowerUp(this._game, this._sprites));
                _powerUp.Initialize();
                _tmpLastPowerUpAdd = gameTime.TotalGameTime;
            }
            foreach (var component in this.Components)
            {
                component.Update(gameTime);  
            }

            
            

            base.Update(gameTime);
        }

        private void bossFire()
        {
            if (Util.Instance.RandomGenerator.Next(100) == 1)
            {
                fireBullit(Direction.Up, new Vector2(_boss.getPositionX() + 48, _boss.getPositionY()), false);
                fireBullit(Direction.Down, new Vector2(_boss.getPositionX() + 48, _boss.getPositionY()), false);
                fireBullit(Direction.DownLeft, new Vector2(_boss.getPositionX() + 48, _boss.getPositionY()), false);
                fireBullit(Direction.DownRight, new Vector2(_boss.getPositionX() + 48, _boss.getPositionY()), false);
                fireBullit(Direction.UpLeft, new Vector2(_boss.getPositionX() + 48, _boss.getPositionY()), false);
                fireBullit(Direction.UpRight, new Vector2(_boss.getPositionX() + 48, _boss.getPositionY()), false);
            }
            

        }

        private void chkCol()
        {
            
            wave1Col();
            wave2Col();
            wave3Col();
            
            //Chk Boss and player colide
            if (_player.CheckCollisionRect(_boss.BoundsRect()))
            {
                _player.hit(10);
                _boss.hit(10);

                // Explosion Sound
                explosion1.Play();
            }
            

            //chk Bullet hist player and boss
            for (int bullit = 0; bullit < _bullets.Length; bullit++)
            {
                //chk if pleyer is hit
                if (_bullets[bullit]._playerBullet == false)
                {
                    if (_player.CheckCollisionRect(_bullets[bullit].BoundsRect()))
                    {
                        _player.hit(10);
                        _bullets[bullit].putInStartPos();
                        // Explosion Sound
                        explosion1.Play();
                       
                    }
                }

                //Chk Boss Hit by player bullet
                if ((_bullets[bullit]._playerBullet)&& (_boss._active))
                {
                    if (_boss.CheckCollisionRect(_bullets[bullit].BoundsRect()))
                    {
                        _boss.hit();
                        _score += 10;
                        _bullets[bullit].putInStartPos();
                        // Explosion Sound
                        explosion1.Play();

                    }
                }


            }
                    
            //Col powerup
                if (_player.CheckCollisionRect(_powerUp.BoundsRect()))
                {
                    //Fix so that pover does not increase above 100 
                    if (_player._power <= 80)
                    {
                        _player.increasePower(20);
                    }
                    else
                    {
                        _player.increasePower(100 - _player._power);
                    }
                    _powerUp.stay();
                }
                if (_player._isDead||(_player._power <= 0))
                {
                    playerDeathReset();
                }
            
        }

        private void wave3Col()
        {
            //Check for colitions betwen player bullits and enemy 3 planes
            for (int plane = 0; plane < _wave3Arr.Length; plane++)
            {
                for (int bullit = 0; bullit < _bullets.Length; bullit++)
                {
                    if (_bullets[bullit]._playerBullet == true)
                    {
                        if (_wave3Arr[plane].CheckCollisionRect(_bullets[bullit].BoundsRect()))
                        {                            
                            _wave3Arr[plane].hit();
                            _bullets[bullit].putInStartPos();

                            // Explosion Sound
                            explosion1.Play();
                            //if (_wave3Arr[plane]._isDying == false)
                            //{
                                
                                _score += 20;
                               
                            //}
                        }
                    }

                }
            }
            //chk col player and ennemy 3;
            for (int plane = 0; plane < _wave3Arr.Length; plane++)
            {
                if (_wave3Arr[plane].CheckCollisionRect(_player.BoundsRect()))
                {
                    //_wave3Arr[plane].hit();
                    if (_wave3Arr[plane]._isDying == false)
                    {
                        _player.hit(20);
                        _wave3Arr[plane].hit();
                        // Explosion Sound
                        explosion1.Play();
                    }
                }
            }
        }

        private void wave2Col()
        {
            //Check for colitions betwen player bullits and enemy 2 planes
            for (int plane = 0; plane < _wave2Arr.Length; plane++)
            {
                for (int bullit = 0; bullit < _bullets.Length; bullit++)
                {
                    if (_bullets[bullit]._playerBullet == true)
                    {
                        if (_wave2Arr[plane].CheckCollisionRect(_bullets[bullit].BoundsRect()))
                        {                            
                            _wave2Arr[plane].hit();
                            _bullets[bullit].putInStartPos();
                            // Explosion Sound
                            explosion1.Play();
                            //if (_wave2Arr[plane]._isDying == false)
                            //{
                                _score += 15;
                            //}
                        }
                    }

                }
            }
            //chk col player and ennemy 2;
            for (int plane = 0; plane < _wave2Arr.Length; plane++)
            {
                if (_wave2Arr[plane].CheckCollisionRect(_player.BoundsRect()))
                {

                    if (_wave2Arr[plane]._isDying == false)
                    {
                        _player.hit();
                        _wave2Arr[plane].hit(15);
                        // Explosion Sound
                        explosion1.Play();
                    }
                }
            }
        }

        private void wave1Col()
        {
            //Check for colitions betwen player bullits and enemy 1 planes
            for (int plane = 0; plane < _wave1Arr.Length; plane++)
            {
                for (int bullit = 0; bullit < _bullets.Length; bullit++)
                {
                    if (_bullets[bullit]._playerBullet == true)
                    {
                        if (_wave1Arr[plane].CheckCollisionRect(_bullets[bullit].BoundsRect()))
                        {                            
                            _wave1Arr[plane].hit();
                            _bullets[bullit].putInStartPos();
                            // Explosion Sound
                            explosion1.Play();
                            //if (_wave1Arr[plane]._isDying == false)
                            //{
                                _score += 10;
                            //}
                        }
                    }

                }
            }
            //chk col player and ennemy 1;
            for (int plane = 0; plane < _wave1Arr.Length; plane++)
            {
                if (_wave1Arr[plane].CheckCollisionRect(_player.BoundsRect()))
                {
                    //_wave1Arr[plane].hit();
                    if (_wave1Arr[plane]._isDying == false)
                    {
                        _player.hit();
                        _wave1Arr[plane].hit();
                        // Explosion Sound
                        explosion1.Play();
                    }
                }
            }
        
        }
        public override void Draw(GameTime gameTime)
        {
            _spriteBatch.GraphicsDevice.Clear(new Color(0, 67, 171));
            _spriteBatch.Begin();
            DrawMap();
            _spriteBatch.DrawString(_fonts, "Score: " + _score, new Vector2(10, 10), Color.Black);
            _spriteBatch.DrawString(_fonts, "Power:  " + _player._power, new Vector2(10, 30), Color.Yellow);
            _spriteBatch.DrawString(_fonts, "Life:  " + _numOfPlayerLifes, new Vector2(10, 50), Color.Red);
            if (_numOfPlayerLifes <= 0)
            {
                _spriteBatch.DrawString(_fonts, "G A M E   O V E R !!!", new Vector2(Util.ScreenWidth/2 - 100, Util.ScreenHeight/2), Color.Red);
            }
            if ((_boss._active) &&(_boss._isDead) && (_numOfPlayerLifes > 0))
            {
                _spriteBatch.DrawString(_fonts, "Y O U  W I N !!!", new Vector2(Util.ScreenWidth / 2 - 100, Util.ScreenHeight / 2), Color.Red);
            }
            _spriteBatch.End();
            foreach (var component in this.Components)
            {
                if(component is DrawableGameComponent)
                    ((DrawableGameComponent)component).Draw(gameTime);
            }
            base.Draw(gameTime);
        }

        private void DrawMap()
        {
            
            Vector2 sea1 = new Vector2(0, 0);
            Vector2 sea2 = new Vector2(0, 0);
            for (int j = 0; j < 20; j++)
            {
                sea1.Y = j * 32 + _mapPosition;
                sea2.Y = j * 32 + _mapPosition;
                for (int i = 0; i < 13; i++)
                {
                    sea1.X = 64 * i;
                    sea2.X = 64 * i + 32;
                    _spriteBatch.Draw(_sprites, sea1, new Rectangle(268, 367, 32, 32), Color.White);
                    _spriteBatch.Draw(_sprites, sea2, new Rectangle(301, 367, 32, 32), Color.White);
                    
                }
            }
            if (_mapPosition == 0)
            {
                _mapPosition = -32;
            }
            else
            {
                _mapPosition++;
            }
        }

        public void fireBullit(Vector2 dir, Vector2 pos, bool playerBullet)
        {
            //bulletTest.launch(pos, dir);
            if (_bulletConter >= 99)
            {
                _bulletConter =0;
            }
            _bullets[_bulletConter].launch(pos, dir, playerBullet);
            _bulletConter++;
            
        }
        public float getPlayerPositionX()
        {
            return _player._position.X;
        }

        private void playerDeathReset()
        {
            _numOfPlayerLifes--;
            if (_numOfPlayerLifes <= 0)
            {
                _player._isDead = true;
            }
            else
            {
                _player.SetReceivingDamageFalse();
                _player._power = 50;
                _player._isDead = false;
                _player._isDying = false;
                _player.putInPosition(Util.ScreenWidth / 2, Util.ScreenHeight - 65);
            }
            
        }

        public void Reset()
        {
            Components.Clear();
            island = new Island(this._game, ref this._sprites);
            Components.Add(island);

            wave1 = new Wave1Handeler(_game, ref this._sprites);
            wave1.Initialize(this);
            Components.Add(wave1);
            wave2 = new Wave2Handeler(_game, ref this._sprites);
            wave2.Initialize(this);
            Components.Add(wave2);
            wave3 = new Wave3Handeler(_game, ref this._sprites);
            wave3.Initialize(this);
            Components.Add(wave3);

            _bullets = new Bullet[100];
            for (int i = 0; i < 100; i++)
            {
                _bullets[i] = new Bullet(_game, ref this._sprites);
                _bullets[i]._position = new Vector2(-100, -100);
                Components.Add(_bullets[i]);
            }
            _player = new PlayerPlane(_game, ref this._sprites);
            _player._power = 50;
            Components.Add(_player);
            _powerUp = new PowerUp(this._game, this._sprites);
            _powerUp.stay();
            Components.Add(_powerUp);
            _boss = new BossPlane(_game, ref this._sprites);
            Components.Add(_boss);

            _score = 0;
            _numOfPlayerLifes = 3;
            _isTheScoreRecorded = false;

        }

    }
}
